home *** CD-ROM | disk | FTP | other *** search
/ Young Minds / Young Minds Interactive CD-ROM.ISO / sdi / notify.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-08  |  3.9 KB  |  159 lines

  1. /************************************  notify.c  *************************/
  2. #include "sdi.h"
  3. #include <sunwindow/notify.h>
  4. #include <sys/ioctl.h>
  5. #include <fcntl.h>
  6.  
  7. /*
  8.  * Copyright 1987 by Mark Weiser.
  9.  * Permission to reproduce and use in any manner whatsoever on Suns is granted
  10.  * so long as this copyright and other identifying marks of authorship
  11.  * in the code and the game remain intact and visible.  Use of this code
  12.  * in other products is reserved to me--I'm working on Mac and IBM versions.
  13.  */
  14.  
  15. /*
  16.  * notifier and timer specific code, including some input handling hacks.
  17.  */
  18.  
  19. /*
  20.  * Begin a series of minor kludges to get good response time at
  21.  * heavy screen loads without running into various SunView bugs
  22.  * involving input notification and non-blocking I/O.  There is
  23.  * probably a bit of overkill here, but the obvious solution
  24.  * (turn on non-blocking once in 'main') does not work.
  25.  */
  26.  
  27. /*
  28.  * See if any mouse clicks have occured.
  29.  */
  30. checkinput()
  31. {
  32.     input_helper(city_fd, citycanvas);
  33.     input_helper(launch_fd, launchcanvas);
  34. }
  35.  
  36. /*
  37.  * Without blocking, exhaust all input on file descripter 'fd' and
  38.  * send it to window 'w'.  
  39.  */
  40. input_helper(fd, w)
  41. Window w;
  42. {
  43.     Event event;
  44.     int old_flags = fcntl(fd, F_GETFL);
  45. /*
  46.  * Have to turn FNDELAY on and off because SunView really doesn't
  47.  * work well with it on under heavy input load.  The result is that
  48.  * we do too much work under light load (when we can afford it), and
  49.  * much less work under heavy load (when it makes sense).  A good balance.
  50.  */
  51.     fcntl(fd, F_SETFL, old_flags | FNDELAY);
  52.     while(! input_readevent(fd, &event)) {
  53.         canvas_event(w, &event);
  54.         event_x(&event) = event_x(&event)-FIELD_MARGIN;
  55.         event_y(&event) = event_y(&event)-FIELD_MARGIN;
  56.         main_event_proc(w, &event, 0);
  57.     }
  58.     fcntl(fd, F_SETFL, old_flags);
  59. }
  60.  
  61. /*
  62.  * Receive notifications of pending input.
  63.  */
  64. Notify_value 
  65. input_notify(me, fd)
  66. {
  67.     if (fd == city_fd) {
  68.         input_helper(city_fd, citycanvas);
  69.     } else if (fd == launch_fd) {
  70.         input_helper(launch_fd, launchcanvas);
  71.     } 
  72. }
  73.  
  74. /*
  75.  * Schedule things from input clients before timers.  The effect
  76.  * is to get all the input before starting to update the screen.
  77. */
  78. Notify_value
  79. scheduler(n, clients)
  80. Notify_client *clients;
  81. {
  82.     int i;
  83.     for (i=0; i < n; i += 1) {
  84.         if (
  85.             clients[i] == (Notify_client)launchcanvas ||
  86.             clients[i] == (Notify_client)citycanvas ||
  87.             clients[i] == (Notify_client)launchframe ||
  88.             clients[i] == (Notify_client)cityframe
  89.             ) {
  90.                 notify_client(clients[i]);
  91.                 clients[i] = NOTIFY_CLIENT_NULL;
  92.         }
  93.     }
  94.     for (i=0; i < n; i += 1) {
  95.         if (clients[i] != NOTIFY_CLIENT_NULL) {
  96.                 notify_client(clients[i]);
  97.                 clients[i] = NOTIFY_CLIENT_NULL;
  98.         }
  99.     }
  100.     return NOTIFY_DONE;
  101. }
  102.  
  103. /*
  104.  * Call procedure f in a little while.
  105.  */
  106.  
  107. struct call_wrapper {
  108.     /* Dynamically allocating a wrapper ensures unique notifier id's. */
  109.     void (*f)();
  110. }
  111.  
  112. do_with_delay(f, secs, usecs)
  113. void (*f)();
  114. int secs, usecs;
  115. {
  116.     Notify_value do_the_call();
  117.     struct call_wrapper *w;
  118.     struct itimerval timer;
  119.  
  120.     /* Sigh, so much work just to wait a bit before starting up. */
  121.     timer.it_interval.tv_usec = 0;
  122.     timer.it_interval.tv_sec = 0;
  123.     timer.it_value.tv_usec = usecs;
  124.     timer.it_value.tv_sec = secs;
  125.      w = (struct call_wrapper *)calloc(sizeof(struct call_wrapper), 1);
  126.     w->f = f;
  127.     notify_set_itimer_func(w, do_the_call,
  128.         ITIMER_REAL, &timer, NULL);
  129. }
  130.  
  131. /*
  132.  * Wrapper to make sure procedures from do_with_delay return good values
  133.  * to the notifier.
  134.  */
  135. Notify_value
  136. do_the_call(w, which)
  137. struct call_wrapper *w;
  138. {
  139.     (*(w->f))();
  140.     free(w);
  141.     return NOTIFY_DONE;
  142. }
  143.  
  144. /* Call this routine when we are suspended, and
  145.  * we want to put off notification.  The parameters
  146.  * are those to notify_set_itimer_func.
  147.  */
  148. suspendor(func, me, which, when)
  149. Notify_value (*func)();
  150. int *me, which;
  151. {
  152.     struct itimerval timer;
  153.     timer.it_interval.tv_usec = 0;
  154.     timer.it_interval.tv_sec = 0;
  155.     timer.it_value.tv_usec = 0;
  156.     timer.it_value.tv_sec = when;
  157.     notify_set_itimer_func(me, func, ITIMER_REAL, &timer, which);
  158. }
  159.